﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Hosting;
using System.Web;
using System.Reflection;
using System.IO;
using System.Collections;
using System.Web.Caching;
using Medianamik.Core.Resources;
using Medianamik.Core.Interfaces;

namespace Medianamik.Core
{
    public class MedianamikVirtualPathProvider : VirtualPathProvider
    {
        private MedianamikAssemblyCollection _assemblies;
        protected MedianamikAssemblyCollection Assemblies
        {
            get
            {
                return _assemblies 
                    ?? (_assemblies = ResourcesUtil.GetAssemblyCollection());
            }
        }
              

        private ResourceInfo GetResourceInfo(string virtualPath)
        {
            IMedianamikAssembly assembly;
            string checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
            if (Assemblies.IsPathVirtual(checkPath, out assembly))
            {
                string resourceName;
                if (assembly.TryGetAssemblyResourceName(checkPath, out resourceName ))
                {
                    return new ResourceInfo(virtualPath, resourceName, assembly.GetAssembly());
                }
                return null;
            }
            throw new CoreException("InvalidPath");
        }

        public override bool FileExists(string virtualPath)
        {
            IMedianamikAssembly assembly;
            if (Assemblies.IsPathVirtual(virtualPath, out assembly))
            {
                ResourceInfo info = GetResourceInfo(virtualPath);
                if (info != null)
                {
                    return true;
                };
            }
            return Previous.FileExists(virtualPath);
        }

        public override bool DirectoryExists(string virtualDir)
        {
            if (Assemblies.IsPathVirtual(virtualDir))
            {
                return true;
            }
            return Previous.DirectoryExists(virtualDir);  
        }

        public override VirtualFile GetFile(string virtualPath)
        {
            var exclusions = new[]
                                 {
                                     "MasterPanel.aspx",
                                     "Login.aspx",
                                     "Login2.aspx"
                                 };

            if(!exclusions.Any(e => virtualPath.ToLower().EndsWith(e.ToLower())) 
                && Previous.FileExists(virtualPath))
                return Previous.GetFile(virtualPath);

            IMedianamikAssembly assembly;
            if (Assemblies.IsPathVirtual(virtualPath, out assembly))
            {

                var resourceInfo = GetResourceInfo(virtualPath);
                if (resourceInfo != null)
                {
                    return new MedianamikVirtualFile(resourceInfo);
                }
            }

            return Previous.GetFile(virtualPath);
        }

        public override VirtualDirectory GetDirectory(string virtualDir)
        {
            if (Assemblies.IsPathVirtual(virtualDir))
                return new MedianamikVirtualDirectory(virtualDir);
            else
                return Previous.GetDirectory(virtualDir);
        }

        public override System.Web.Caching.CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
        {
            if (Assemblies.IsPathVirtual(virtualPath))
            {
                return new DummyCacheDependency(); 
            }
            return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);  
        }


        public void RegisterAssembly(IMedianamikAssembly pAssembly)
        {
            Assemblies.Add(pAssembly);
        }

    }

    public class MedianamikVirtualDirectory : VirtualDirectory
    {

        public MedianamikVirtualDirectory(string virtualPath) : base(virtualPath) { }

        private ArrayList children = new ArrayList();
        public override IEnumerable Children { get { return children; } }
        private ArrayList directories = new ArrayList();
        public override IEnumerable Directories { get { return directories; } }
        private ArrayList files = new ArrayList();
        public override IEnumerable Files { get { return files; } }
    }

    public class MedianamikVirtualFile : VirtualFile
    {
        private string _resourceName;
        private Assembly _assembly;

        public MedianamikVirtualFile(ResourceInfo resourceInfo)
            : base(resourceInfo.VirtualPath )
        {
            _resourceName = resourceInfo.ResourceName;
            _assembly = resourceInfo.Assembly;
        }

        public override Stream Open()
        {
            return Sugar.Resources.GetResourceReader(_resourceName, _assembly).BaseStream; 
        }

        
    }

    public class DummyCacheDependency : CacheDependency
    {

    }

    public class ResourceInfo
    {
       public Assembly Assembly { get; set; }
       public string ResourceName { get; set; }
       public string VirtualPath { get; set; }

        public ResourceInfo(string pVirtualPath, string pResourceName, Assembly pAssembly )
        {
            Assembly = pAssembly;
            ResourceName = pResourceName;
            VirtualPath = pVirtualPath;
        }
    }
}
